home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / goodies / qtmoviefromprocs / qtmoviefromprocs.c < prev    next >
Encoding:
Text File  |  2000-09-28  |  22.2 KB  |  765 lines

  1. //////////
  2. //
  3. //    File:        QTMovieFromProcs.c
  4. //
  5. //    Contains:    Sample code for creating a QuickTime movie using application-defined procedures.
  6. //
  7. //    Written by:    Tim Monroe
  8. //                Based on sample code in the QuickTime 3.0 Reference document.
  9. //
  10. //    Copyright:    © 1998-1999 by Apple Computer, Inc., all rights reserved.
  11. //
  12. //    Change History (most recent first):
  13. //
  14. //       <7>         02/09/99    rtm        minor tweaks; verified on Windows and Mac; added more comments
  15. //       <6>         02/05/99    rtm        added code to enumerate all components that can export-by-procs
  16. //                                    add their names to the Test menu, and use the selected exporter
  17. //       <5>         02/02/99    rtm        reworked prompt and filename handling to remove "\p" sequences
  18. //       <4>         11/11/98    rtm        minor tweaks; added more comments
  19. //       <3>         11/06/98    rtm        incorporated settings file code from QTHintMovies.c
  20. //       <2>         10/19/98    rtm        further work; works fine on Mac and Windows
  21. //       <1>         10/16/98    rtm        first file
  22. //     
  23. //    QuickTime 3.0 provides functions that allow you to create a movie using data supplied by one or more
  24. //    application-defined procedures. In particular, you use the function MovieExportAddDataSource to add a
  25. //    track-generating procedure and you use the function MovieExportFromProceduresToDataRef to do the actual
  26. //    movie exporting.
  27. //
  28. //    In this example, we will create a QuickTime movie with a video track and an audio track; we generate the
  29. //    video track by drawing a series of individual frames, and we generate the audio track by generating
  30. //    10 seconds of silence.
  31. //
  32. //    This sample code finds all movie export components that can export using application-defined procedures,
  33. //    adds their names to a menu, and then calls the appropriate exporter when the user selects a menu item. The
  34. //    only real interesting code in the QTMenu_ functions is the code that enumerates the available exporters
  35. //    that can export-by-procedures.
  36. //
  37. //    This sample code snippet also illustrates how to configure the movie export component, using either
  38. //    MovieExportDoUserDialog to display the component's settings dialog or MovieExportSetSettingsFromAtomContainer
  39. //    to restore some previously-saved settings from an atom container. Note that any settings configured by the
  40. //    user or by a call to MovieExportSetSettingsFromAtomContainer may be overridden by the settings returned by 
  41. //    your track property callback function (in this sample, the functions QTMoovProcs_AudioTrackPropertyProc and
  42. //    QTMoovProcs_VideoTrackPropertyProc).
  43. //
  44. //////////
  45.  
  46.  
  47. #include "QTMovieFromProcs.h"
  48.  
  49.  
  50. // global variables
  51. QTMoovProcsAudioDataRec                gAudioDataRec;
  52. QTMoovProcsVideoDataRec                gVideoDataRec;
  53.  
  54. MovieExportGetPropertyUPP            gAudioPropProcUPP = NULL;
  55. MovieExportGetDataUPP                gAudioDataProcUPP = NULL;
  56.  
  57. MovieExportGetPropertyUPP            gVideoPropProcUPP = NULL;
  58. MovieExportGetDataUPP                gVideoDataProcUPP = NULL;
  59.  
  60. QTProcExportersInfo                    gExporterInfo;
  61.  
  62. extern ConstStr255Param                gSettingsFileName;
  63.  
  64. #if TARGET_OS_WIN32
  65. extern HWND                            ghWnd;                    // the MDI frame window; this window has the menu bar
  66. #include "ComResource.h"
  67. #endif
  68.  
  69.  
  70. //////////
  71. //
  72. // QTMoovProcs_CreateMovieFromProcs
  73. // Create a QuickTime movie using audio- and video-data generating procedures.
  74. //
  75. //////////
  76.  
  77. OSErr QTMoovProcs_CreateMovieFromProcs (MovieExportComponent theExporter, Boolean thePromptUser)
  78. {    
  79.     StandardFileReply            myReply;
  80.     Handle                        myDataRef = NULL;
  81.     FSSpec                        myPrefsFile;
  82.     StringPtr                     myMoviePrompt = QTUtils_ConvertCToPascalString(kSaveMoviePrompt);
  83.     StringPtr                     myMovieFileName = QTUtils_ConvertCToPascalString(kSaveMovieFileName);
  84.     OSErr                        myErr = userCanceledErr;
  85.  
  86.     // have the user select the name of the new movie file
  87.     StandardPutFile(myMoviePrompt, myMovieFileName, &myReply);
  88.     if (!myReply.sfGood)
  89.         goto bail;
  90.     
  91.     // replace any existing file having that name, if the user so desires
  92.     if (myReply.sfReplacing) {
  93.         myErr = FSpDelete(&myReply.sfFile);
  94.         if (myErr != noErr)
  95.             goto bail;
  96.     }
  97.  
  98.     // add sources of audio and video data to the movie exporter;
  99.     // we ignore errors here, since some exporters might be audio-only or video-only
  100.     myErr = QTMoovProcs_AddAudioSourceToExporter(theExporter);
  101.     myErr = QTMoovProcs_AddVideoSourceToExporter(theExporter);
  102.         
  103.     // create a data reference for the output movie file
  104.     myDataRef = NewHandle(sizeof(Handle));
  105.     if (myDataRef == NULL)
  106.         goto bail;
  107.  
  108.     QTNewAlias(&myReply.sfFile, (AliasHandle *)&myDataRef, true);
  109.     
  110.     // get the preferences file for this application
  111.     QTMoovProcs_GetPrefsFileSpec(&myPrefsFile, (void *)(&myReply.sfFile));
  112.     
  113.     // read existing movie exporter settings from a file; if we aren't going to prompt
  114.     // the user for exporter settings, these stored settings will be used; otherwise,
  115.     // these stored settings will be used as initial values in the settings dialog box
  116.     QTUtils_GetExporterSettingsFromFile(theExporter, &myPrefsFile);
  117.     
  118.     if (thePromptUser) {
  119.         Boolean        myCancelled = false;
  120.         
  121.         // display a dialog box to prompt the user for desired movie exporter settings        
  122.         myErr = MovieExportDoUserDialog(theExporter, NULL, NULL, 0, 0, &myCancelled);
  123.         if (myCancelled)
  124.             goto bail;
  125.         
  126.         // save the existing settings into our preferences file
  127.         QTUtils_SaveExporterSettingsInFile(theExporter, &myPrefsFile);
  128.     }
  129.         
  130.     // export the audio and video data to the data reference
  131.     myErr = MovieExportFromProceduresToDataRef(theExporter, myDataRef, rAliasType);
  132.     
  133. bail:
  134.     free(myMoviePrompt);
  135.     free(myMovieFileName);
  136.  
  137.     // dispose of the routine descriptors
  138.     DisposeRoutineDescriptor(gAudioPropProcUPP);
  139.     DisposeRoutineDescriptor(gAudioDataProcUPP);
  140.     DisposeRoutineDescriptor(gVideoPropProcUPP);
  141.     DisposeRoutineDescriptor(gVideoDataProcUPP);
  142.     
  143.     // dispose of any memory that we allocated before or during the export operation
  144.     if (myDataRef != NULL)
  145.         DisposeHandle(myDataRef);
  146.     
  147.     if (gAudioDataRec.fSoundData != NULL)
  148.         DisposePtr(gAudioDataRec.fSoundData);
  149.         
  150.     if (gAudioDataRec.fSoundDescription != NULL)
  151.         DisposeHandle((Handle)gAudioDataRec.fSoundDescription);
  152.         
  153.     if (gVideoDataRec.fGWorld != NULL)
  154.         DisposeGWorld(gVideoDataRec.fGWorld);
  155.         
  156.     if (gVideoDataRec.fImageDescription != NULL)
  157.         DisposeHandle((Handle)gVideoDataRec.fImageDescription);
  158.         
  159.     return(myErr);
  160. }
  161.  
  162.  
  163. //////////
  164. //
  165. // QTMoovProcs_AddAudioSourceToExporter
  166. // Attach a source for audio data to the specified movie exporter.
  167. //
  168. //////////
  169.  
  170. OSErr QTMoovProcs_AddAudioSourceToExporter (MovieExportComponent theExporter)
  171. {    
  172.     SoundDescriptionPtr            mySoundDescPtr = NULL;
  173.     short                        myIndex;
  174.     OSErr                        myErr = memFullErr;
  175.         
  176.     // create a buffer to hold the audio data
  177.     gAudioDataRec.fSoundData = NewPtrClear(kSoundBufferSize);
  178.     if (gAudioDataRec.fSoundData == NULL)
  179.         goto bail;
  180.     
  181.     // our sound data format is 8-bit, offset binary, where a sample point is an 8-bit value
  182.     // in the range 0 to 255 (0x00 to 0xFF); for silence, set all sample points to 128 (0x80)
  183.     for (myIndex = 0; myIndex < kSoundBufferSize; myIndex++)
  184.         gAudioDataRec.fSoundData[myIndex] = (UInt8)128;
  185.     
  186.     // create and configure a sound description record
  187.     gAudioDataRec.fSoundDescription = (SoundDescriptionHandle)NewHandleClear(sizeof(SoundDescription));
  188.     if (gAudioDataRec.fSoundDescription == NULL)
  189.         goto bail;
  190.  
  191.     mySoundDescPtr = *(gAudioDataRec.fSoundDescription);
  192.     mySoundDescPtr->descSize = sizeof(SoundDescription);
  193.     mySoundDescPtr->dataFormat = k8BitOffsetBinaryFormat;
  194.     mySoundDescPtr->numChannels = 1;
  195.     mySoundDescPtr->sampleSize = 8;
  196.     mySoundDescPtr->sampleRate = kAudioSampleRate << 16;
  197.     
  198.     // create UPPs for the two app-defined export functions
  199.     gAudioPropProcUPP = NewMovieExportGetPropertyProc(QTMoovProcs_AudioTrackPropertyProc);
  200.     gAudioDataProcUPP = NewMovieExportGetDataProc(QTMoovProcs_AudioTrackDataProc);
  201.     
  202.     myErr = MovieExportAddDataSource(theExporter,
  203.                                         SoundMediaType,
  204.                                         kAudioSampleRate,
  205.                                         &gAudioDataRec.fTrackID,
  206.                                         gAudioPropProcUPP,
  207.                                         gAudioDataProcUPP,
  208.                                         &gAudioDataRec);
  209.  
  210. bail:
  211.     return(myErr);
  212. }
  213.  
  214.  
  215. //////////
  216. //
  217. // QTMoovProcs_AddVideoSourceToExporter
  218. // Attach a source for video data to the specified movie exporter.
  219. //
  220. //////////
  221.  
  222. OSErr QTMoovProcs_AddVideoSourceToExporter (MovieExportComponent theExporter)
  223. {    
  224.     OSErr    myErr = noErr;
  225.  
  226.     gVideoDataRec.fGWorld = NULL;    
  227.     gVideoDataRec.fImageDescription = NULL;
  228.     
  229.     // create UPPs for the two app-defined export functions
  230.     gVideoPropProcUPP = NewMovieExportGetPropertyProc(QTMoovProcs_VideoTrackPropertyProc);
  231.     gVideoDataProcUPP = NewMovieExportGetDataProc(QTMoovProcs_VideoTrackDataProc);
  232.     
  233.     myErr = MovieExportAddDataSource(theExporter,
  234.                                         VideoMediaType,
  235.                                         kVideoSampleRate,
  236.                                         &gVideoDataRec.fTrackID,
  237.                                         gVideoPropProcUPP,
  238.                                         gVideoDataProcUPP,
  239.                                         &gVideoDataRec);
  240.  
  241.     return(myErr);
  242. }
  243.  
  244.  
  245. //////////
  246. //
  247. // QTMoovProcs_AudioTrackPropertyProc
  248. // Handle requests for information about the output audio data.
  249. //
  250. //////////
  251.  
  252. PASCAL_RTN OSErr QTMoovProcs_AudioTrackPropertyProc (void *theRefcon, long theTrackID, OSType thePropertyType, void *thePropertyValue)
  253. {
  254. #pragma unused(theRefcon, theTrackID)
  255.  
  256.     OSErr    myErr = noErr;
  257.     
  258.     switch (thePropertyType) {
  259.     
  260.         case scSoundSampleRateType:
  261.             *(Fixed *)thePropertyValue = 32000L << 16;
  262.             break;
  263.             
  264.         default:
  265.             myErr = paramErr;    // non-zero value means: use default value provided by export component
  266.             break;
  267.     }
  268.     
  269.     return(myErr);
  270. }
  271.  
  272.  
  273. //////////
  274. //
  275. // QTMoovProcs_AudioTrackDataProc
  276. // Provide the output audio data.
  277. //
  278. //////////
  279.  
  280. PASCAL_RTN OSErr QTMoovProcs_AudioTrackDataProc (void *theRefcon, MovieExportGetDataParams *theParams)
  281. {
  282.     QTMoovProcsAudioDataRecPtr    myAudioDataRecPtr;
  283.     OSErr                        myErr = noErr;
  284.     
  285.     myAudioDataRecPtr = (QTMoovProcsAudioDataRecPtr)theRefcon;
  286.  
  287.     // end the data after desired length of movie
  288.     if (theParams->requestedTime > kAudioSampleRate * kMovieLengthInSeconds)
  289.         return(eofErr);
  290.     
  291.     theParams->actualTime = theParams->requestedTime;
  292.     theParams->dataPtr = myAudioDataRecPtr->fSoundData;
  293.     theParams->dataSize = kSoundBufferSize;
  294.     theParams->desc = (SampleDescriptionHandle)(myAudioDataRecPtr->fSoundDescription);
  295.     theParams->descType = SoundMediaType;
  296.     theParams->descSeed = 1;
  297.     theParams->actualSampleCount = kSoundBufferSize;
  298.     theParams->durationPerSample = 1;
  299.     theParams->sampleFlags = 0L;
  300.     
  301.     return(myErr);
  302. }
  303.  
  304.  
  305. //////////
  306. //
  307. // QTMoovProcs_VideoTrackPropertyProc
  308. // Handle requests for information about the output video data.
  309. //
  310. //////////
  311.  
  312. PASCAL_RTN OSErr QTMoovProcs_VideoTrackPropertyProc (void *theRefcon, long theTrackID, OSType thePropertyType, void *thePropertyValue)
  313. {
  314. #pragma unused(theRefcon, theTrackID)
  315.  
  316.     OSErr    myErr = noErr;
  317.     
  318.     switch (thePropertyType) {
  319.         case movieExportWidth:
  320.             *(Fixed *)thePropertyValue = kVideoFrameWidth << 16;
  321.             break;
  322.             
  323.         case movieExportHeight:
  324.             *(Fixed *)thePropertyValue = kVideoFrameHeight << 16;
  325.             break;
  326.  
  327.         case scSpatialSettingsType: {
  328.             SCSpatialSettings        *mySpatialSettings = thePropertyValue;
  329.             
  330.             mySpatialSettings->codecType = kJPEGCodecType;
  331.             mySpatialSettings->codec = 0;
  332.             mySpatialSettings->depth = 0;
  333.             mySpatialSettings->spatialQuality = codecNormalQuality;
  334.         }
  335.             break;
  336.  
  337.         default:
  338.             myErr = paramErr;    // non-zero value means: use default value provided by export component
  339.             break;
  340.     }
  341.     
  342.     return(myErr);
  343. }
  344.  
  345.  
  346. //////////
  347. //
  348. // QTMoovProcs_VideoTrackDataProc
  349. // Provide the output audio data.
  350. //
  351. //////////
  352.  
  353. PASCAL_RTN OSErr QTMoovProcs_VideoTrackDataProc (void *theRefcon, MovieExportGetDataParams *theParams)
  354. {    
  355.     QTMoovProcsVideoDataRecPtr    myVideoDataRecPtr;
  356.     PixMapHandle                myPixMap = NULL;
  357.     Rect                        myRect;        
  358.     CGrafPtr                    myOldPort = NULL;
  359.     GDHandle                    myOldDevice = NULL;
  360.     Str255                        myString;
  361.     static long                    myFrameNum = 0;
  362.     OSErr                        myErr = noErr;
  363.     
  364.     myVideoDataRecPtr = (QTMoovProcsVideoDataRecPtr)theRefcon;
  365.     
  366.     // end the data after desired length of movie
  367.     if (theParams->requestedTime > kVideoSampleRate * kMovieLengthInSeconds)
  368.         return(eofErr);
  369.     
  370.     // set the size of the video frame
  371.     MacSetRect(&myRect, 0, 0, kVideoFrameWidth, kVideoFrameHeight);
  372.  
  373.     // if we haven't allocated a GWorld yet, do so now
  374.     if (myVideoDataRecPtr->fGWorld == NULL) {
  375.         NewGWorld(&(myVideoDataRecPtr->fGWorld), 32, &myRect, NULL, NULL, (GWorldFlags)0);
  376.         if (myVideoDataRecPtr->fGWorld == NULL)
  377.             return(memFullErr);
  378.             
  379.         myPixMap = GetGWorldPixMap(myVideoDataRecPtr->fGWorld);
  380.         if (myPixMap == NULL)
  381.             return(memFullErr);
  382.         
  383.         LockPixels(myPixMap);
  384.         
  385.         myErr = MakeImageDescriptionForPixMap(myPixMap, &(myVideoDataRecPtr->fImageDescription));
  386.         if (myErr != noErr)
  387.             goto bail;
  388.     }
  389.     
  390.     GetGWorld(&myOldPort, &myOldDevice);
  391.     SetGWorld(myVideoDataRecPtr->fGWorld, NULL);
  392.     
  393.     // draw a frame: white rectangle with black frame number centered horizontally in frame
  394.     EraseRect(&myRect);
  395.     ForeColor(whiteColor);
  396.     PaintRect(&myRect);
  397.  
  398.     ForeColor(blackColor);
  399.     
  400.     NumToString(++myFrameNum, myString);
  401.     MoveTo((short)(myRect.right / 2) - (StringWidth(myString) / 2), (short)(myRect.bottom / 2));
  402.     TextSize((short)(myRect.bottom / 4));
  403.     DrawString(myString);
  404.  
  405.     theParams->actualTime = theParams->requestedTime;
  406.     theParams->dataPtr = GetPixBaseAddr(GetGWorldPixMap(myVideoDataRecPtr->fGWorld));
  407.     theParams->dataSize = (**(myVideoDataRecPtr->fImageDescription)).dataSize;
  408.     theParams->desc = (SampleDescriptionHandle)(myVideoDataRecPtr->fImageDescription);
  409.     theParams->descType = VideoMediaType;
  410.     theParams->descSeed = 1;
  411.     theParams->actualSampleCount = 1;
  412.     theParams->durationPerSample = kVideoFrameDuration;
  413.     theParams->sampleFlags = 0L;
  414.  
  415. bail:
  416.     // restore the original graphics port and device
  417.     SetGWorld(myOldPort, myOldDevice);
  418.     
  419.     return(myErr);
  420. }
  421.  
  422.  
  423. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  424. //
  425. // Menu utilities.
  426. //
  427. // Use these functions to add component names to a menu and to handle user selections in that menu. These
  428. // exist mainly to illustrate how to find all movie export components that can export using application-
  429. // defined procedures. 
  430. //
  431. // It's useful to remember that Macintosh menu items are numbered from 1, whereas Windows menu items are
  432. // numbered from 0.
  433. //
  434. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  435.  
  436. //////////
  437. //
  438. // QTMenu_InitializeTestMenu
  439. // Initialize the Test menu; add component names to it.
  440. //
  441. //////////
  442.  
  443. OSErr QTMenu_InitializeTestMenu (void)
  444. {
  445.     short            myIndex;
  446.     short            myNumItems;
  447.  
  448. #if TARGET_OS_MAC
  449.     gExporterInfo.fTestMenuHandle = GetMenuHandle(kTestMenuID);
  450.     
  451.     // remove any existing menu items
  452.     myNumItems = CountMenuItems(gExporterInfo.fTestMenuHandle);
  453.     for (myIndex = 0; myIndex < myNumItems; myIndex++)
  454.         DeleteMenuItem(gExporterInfo.fTestMenuHandle, 1);
  455. #elif TARGET_OS_WIN32
  456.     gExporterInfo.fTestMenuHandle = GetSubMenu(GetMenu(ghWnd), WINDOWMENU - 1);
  457.  
  458.     // remove any existing menu items
  459.     myNumItems = GetMenuItemCount(gExporterInfo.fTestMenuHandle);
  460.     for (myIndex = 0; myIndex < myNumItems; myIndex++)
  461.         RemoveMenu(gExporterInfo.fTestMenuHandle, 0, MF_BYPOSITION);
  462. #endif
  463.  
  464.     gExporterInfo.fNextAvailIndex = 0;
  465.     
  466.     // add names of all components that can export-by-procedures to Test menu
  467.     QTMenu_AddComponentNamesToMenu();
  468.     
  469.     return(noErr);
  470. }
  471.  
  472.  
  473. //////////
  474. //
  475. // QTMenu_AddComponentNamesToMenu
  476. // Add the name of all movie export components that can export-by-procedures to the Test menu.
  477. //
  478. //////////
  479.  
  480. OSErr QTMenu_AddComponentNamesToMenu (void)
  481. {
  482.     Component                myComponent = NULL;
  483.     Handle                    myCompName = NewHandleClear(0);
  484.     ComponentDescription    myCompDesc;
  485.     
  486.     // find all movie export components that can export-by-procedures
  487.     do {
  488.         myCompDesc.componentType = MovieExportType;
  489.         myCompDesc.componentSubType = 0;
  490.         myCompDesc.componentManufacturer = 0;
  491.         myCompDesc.componentFlags = canMovieExportFromProcedures;
  492.         myCompDesc.componentFlagsMask = canMovieExportFromProcedures;
  493.     
  494.         myComponent = FindNextComponent(myComponent, &myCompDesc);
  495.         if (myComponent != NULL) {
  496.             // get the component information
  497.             GetComponentInfo(myComponent, &myCompDesc, myCompName, NULL, NULL);
  498.  
  499.             // add the component's name to the menu
  500. #if TARGET_OS_MAC        
  501.             MacAppendMenu(gExporterInfo.fTestMenuHandle, (StringPtr)*myCompName);
  502. #elif TARGET_OS_WIN32
  503.             AppendMenu(gExporterInfo.fTestMenuHandle, MF_STRING | MF_ENABLED, MENU_IDENTIFIER(kTestMenu, gExporterInfo.fNextAvailIndex + 1), p2cstr((StringPtr)*myCompName));
  504. #endif            
  505.             // keep track of this component
  506.             gExporterInfo.fComponentType[gExporterInfo.fNextAvailIndex] = myCompDesc.componentType;
  507.             gExporterInfo.fComponentSubType[gExporterInfo.fNextAvailIndex] = myCompDesc.componentSubType;
  508.             gExporterInfo.fComponentManufacturer[gExporterInfo.fNextAvailIndex] = myCompDesc.componentManufacturer;
  509.             
  510.             gExporterInfo.fNextAvailIndex++;
  511.         }
  512.     } while (myComponent != NULL);
  513.     
  514.     if (myCompName != NULL)
  515.         DisposeHandle(myCompName);
  516.     
  517.     return(noErr);
  518. }
  519.  
  520.  
  521. //////////
  522. //
  523. // QTMenu_HandleTestMenu
  524. // Handle user selection of items in the Test menu.
  525. //
  526. //////////
  527.  
  528. OSErr QTMenu_HandleTestMenu (UInt16 theMenuItem)
  529. {
  530.     MovieExportComponent        myExporter = NULL;
  531.     ComponentDescription        myCompDesc;
  532.     short                        myIndex; 
  533.     OSErr                        myErr = noErr;
  534.     
  535.     myIndex = MENU_ITEM(theMenuItem) - 1;
  536.     if ((myIndex < 0) || (myIndex >= gExporterInfo.fNextAvailIndex))
  537.         return(paramErr);
  538.     
  539.     myCompDesc.componentType = gExporterInfo.fComponentType[myIndex];
  540.     myCompDesc.componentSubType = gExporterInfo.fComponentSubType[myIndex];
  541.     myCompDesc.componentManufacturer = gExporterInfo.fComponentManufacturer[myIndex];
  542.     myCompDesc.componentFlags = canMovieExportFromProcedures;
  543.     myCompDesc.componentFlagsMask = canMovieExportFromProcedures;
  544.  
  545.     // open the selected movie export component
  546.     myExporter = OpenComponent(FindNextComponent(NULL, &myCompDesc));
  547.     if (myExporter == NULL)
  548.         return(badComponentType);
  549.         
  550.     // create the movie using application-defined procedures
  551.     myErr = QTMoovProcs_CreateMovieFromProcs(myExporter, true);
  552.     
  553.     // close the movie export component
  554.     if (myExporter != NULL)
  555.         CloseComponent(myExporter);
  556.         
  557.     return(myErr);
  558. }
  559.  
  560.  
  561. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  562. //
  563. // Settings utilities.
  564. //
  565. // Use these functions to save/retrieve movie exporter settings into/from a preferences file.
  566. //
  567. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  568.  
  569. //////////
  570. //
  571. // QTMoovProcs_GetPrefsFileSpec
  572. // Fill in the specified FSSpec with info about this application's preferences file.
  573. //
  574. // The theRefCon parameter is a pointer to some application-specific data, which you
  575. // might use to find the preferences file; here, we assume it's a pointer to an FSSpec
  576. // for the output hinted file. We'll specify a preferences file in the same folder as
  577. // the hinted file that has the name specified by the global variable gSettingsFileName.
  578. //
  579. //////////
  580.  
  581. OSErr QTMoovProcs_GetPrefsFileSpec (FSSpecPtr thePrefsSpecPtr, void *theRefCon)
  582. {
  583.     FSSpecPtr    myFSSpecPtr = (FSSpecPtr)theRefCon;
  584.     OSErr        myErr = noErr;
  585.  
  586.     if (myFSSpecPtr == NULL)
  587.         return(paramErr);
  588.         
  589.     myErr = FSMakeFSSpec(myFSSpecPtr->vRefNum, myFSSpecPtr->parID, gSettingsFileName, thePrefsSpecPtr);
  590.     
  591.     return(myErr);
  592. }
  593.  
  594.  
  595. //////////
  596. //
  597. // QTUtils_SaveExporterSettingsInFile
  598. // Get the current settings of the specified movie exporter and save them into a file.
  599. //
  600. //////////
  601.  
  602. OSErr QTUtils_SaveExporterSettingsInFile (MovieExportComponent theExporter, FSSpecPtr theFSSpecPtr)
  603. {    
  604.     QTAtomContainer        myContainer = NULL;
  605.     ComponentResult        myErr = noErr;
  606.         
  607.     myErr = MovieExportGetSettingsAsAtomContainer(theExporter, &myContainer);
  608.     if (myErr != noErr)
  609.         goto bail;
  610.         
  611.     myErr = QTUtils_WriteHandleToFile((Handle)myContainer, theFSSpecPtr);
  612.  
  613. bail:
  614.     if (myContainer != NULL)
  615.         QTDisposeAtomContainer(myContainer);
  616.         
  617.     return((OSErr)myErr);
  618. }
  619.  
  620.  
  621. //////////
  622. //
  623. // QTUtils_GetExporterSettingsFromFile
  624. // Read the movie exporter settings saved in the specified file.
  625. //
  626. //////////
  627.  
  628. OSErr QTUtils_GetExporterSettingsFromFile (MovieExportComponent theExporter, FSSpecPtr theFSSpecPtr)
  629. {    
  630.     Handle                myHandle = NULL;
  631.     ComponentResult        myErr = fnfErr;        // assume we cannot find the file
  632.         
  633.     myHandle = QTUtils_ReadHandleFromFile(theFSSpecPtr);
  634.     if (myHandle == NULL)
  635.         goto bail;
  636.         
  637.     myErr = MovieExportSetSettingsFromAtomContainer(theExporter, (QTAtomContainer)myHandle);
  638.         
  639. bail:
  640.     if (myHandle != NULL)
  641.         DisposeHandle(myHandle);
  642.         
  643.     return((OSErr)myErr);
  644. }
  645.  
  646.  
  647. //////////
  648. //
  649. // QTUtils_WriteHandleToFile
  650. // Write the data in the specified handle into the specified file;
  651. // if the file already exists, it is overwritten.
  652. //
  653. //////////
  654.  
  655. OSErr QTUtils_WriteHandleToFile (Handle theHandle, FSSpecPtr theFSSpecPtr)
  656. {
  657.     short            myRefNum = 0;
  658. #if TARGET_OS_MAC    
  659.     short            myVolNum;
  660. #endif
  661.     long            mySize = 0;
  662.     OSErr            myErr = paramErr;
  663.  
  664.     if (theHandle == NULL)
  665.         goto bail;
  666.  
  667.     mySize = GetHandleSize(theHandle);
  668.     if (mySize == 0)
  669.         goto bail;
  670.  
  671.     HLock(theHandle);
  672.     
  673.     // delete the file;
  674.     // if it doesn't exist yet, we'll get an error (fnfErr), which we just ignore
  675.     myErr = FSpDelete(theFSSpecPtr);
  676.     
  677.     // create and open the file
  678.     myErr = FSpCreate(theFSSpecPtr, kSettingsFileCreator, kSettingsFileType, smSystemScript);
  679.  
  680.     if (myErr == noErr)
  681.         myErr = FSpOpenDF(theFSSpecPtr, fsRdWrPerm, &myRefNum);
  682.     
  683.     // position the file mark to the beginning of the file and write the data
  684.     if (myErr == noErr)
  685.         myErr = SetFPos(myRefNum, fsFromStart, 0);
  686.  
  687.     if (myErr == noErr)
  688.         myErr = FSWrite(myRefNum, &mySize, *theHandle);
  689.  
  690.     if (myErr == noErr)
  691.         myErr = SetFPos(myRefNum, fsFromStart, mySize);
  692.  
  693.     // resize the file to the number of bytes written
  694.     if (myErr == noErr)
  695.         myErr = SetEOF(myRefNum, mySize);
  696.                 
  697.     // close the file             
  698.     if (myErr == noErr)        
  699.         myErr = FSClose(myRefNum);
  700.  
  701. #if TARGET_OS_MAC    
  702.     // flush the volume
  703.     if (myErr == noErr)        
  704.         myErr = GetVRefNum(myRefNum, &myVolNum);
  705.  
  706.     if (myErr == noErr)        
  707.         myErr = FlushVol(NULL, myVolNum);
  708. #endif    
  709.  
  710. bail:
  711.     HUnlock(theHandle);
  712.  
  713.     return(myErr);
  714. }
  715.  
  716.  
  717. //////////
  718. //
  719. // QTUtils_ReadHandleFromFile
  720. // Read the data in the specified file into a new handle.
  721. //
  722. //////////
  723.  
  724. Handle QTUtils_ReadHandleFromFile (FSSpecPtr theFSSpecPtr)
  725. {
  726.     Handle            myHandle = NULL;
  727.     short            myRefNum = 0;
  728.     long            mySize = 0;
  729.     OSErr            myErr = noErr;
  730.  
  731.     // open the file
  732.     myErr = FSpOpenDF(theFSSpecPtr, fsRdWrPerm, &myRefNum);
  733.     
  734.     if (myErr == noErr)
  735.         myErr = SetFPos(myRefNum, fsFromStart, 0);
  736.  
  737.     // get the size of the file data
  738.     if (myErr == noErr)
  739.         myErr = GetEOF(myRefNum, &mySize);
  740.         
  741.     // allocate a new handle
  742.     if (myErr == noErr)
  743.         myHandle = NewHandleClear(mySize);
  744.     
  745.     if (myHandle == NULL)
  746.         goto bail;
  747.  
  748.     HLock(myHandle);
  749.  
  750.     // read the data from the file into the handle
  751.     if (myErr == noErr)
  752.         myErr = FSRead(myRefNum, &mySize, *myHandle);
  753.  
  754. bail:
  755.     HUnlock(myHandle);
  756.     
  757.     if (myRefNum != 0)        
  758.         FSClose(myRefNum);
  759.  
  760.     return(myHandle);
  761. }
  762.  
  763.  
  764.  
  765.